#include<assert.h>
#include<string.h>
#include<iostream>

using namespace std;

namespace xyx
{
    class string
    {
    public:
    
    typedef char* iterator;
    typedef const char* const_iterator;

    iterator begin()
    {
        return _str;
    }

    iterator end()
    {
        return _str + _size;
    }

    const_iterator begin() const
    {
        return _str;
    }

    const_iterator end() const
    {
        return _str + _size;
    }
    
    string(const string& s)
        :_str(nullptr)
        ,_capacity(0)
         ,_size(0)
    {
       // _str = new char[s._capacity + 1];
       // //strcpy(_str,s._str);
       // memcpy(_str, s._str,s._size + 1);
       // _size = s._size;
       // _capacity = s._capacity;
       
        string tmp(s._str);
        swap(tmp);
    }

    string(const char* str = "")
    {
        _size = strlen(str);
        _capacity = _size;
        _str = new char[_capacity];
        strcpy(_str, str);
    }
    
    ~string()
    {
        delete [] _str;
        _capacity = _size = 0;
    }

    const char* c_str() const
    {
        return _str;
    }
    
    size_t size() const
    {
        return _size;
    }
    
    char& operator[](size_t pos)
    {
        assert(pos <= _size);
        return _str[pos];
    }
    
    const char& operator[](size_t pos) const
    {
        assert(pos <= _size);
        return _str[pos];
    }
    
    void reserve(size_t n = 0)
    {
        //n必须大于_capacity
        if(n > _capacity)
        {
            char* tmp = new char[n];
            //strcpy(tmp, _str);
            memcpy(tmp, _str, _size + 1);
            delete [] _str;
            _str = tmp;
            _capacity = n;
        }
    }
    
    void push_back(char ch)
    {
        //判断容量
        if(_capacity == _size)
        {
            reserve(_capacity == 0 ? 4 : _capacity * 2);
        }

        _str[_size] = ch;
        _size++;
        _str[_size] = '\0';

    }

    void append(const char* str)
    {
        size_t len = strlen(str);
        if(_size + len >_capacity)
        {
            reserve((_capacity + len) * 2);
        }
        //strcpy(_str + _size, str);
        memcpy(_str + _size, str, strlen(str) + 1);
        _size += len;
    }

    size_t capacity() const
    {
        return _capacity;
    }
    
    string& operator+=(char ch)
    {
        push_back(ch);
        return *this;
    }

    string& operator+=(const char* str)
    {
        append(str);
        return *this;
    }
    
    void insert(size_t pos, size_t n, char ch)
    {
        assert(pos <= _size);

        if(_size + n > _capacity)
        {
            reserve((n + _capacity) * 2);
        }
        
        //挪动pos位置后的数据
        size_t end = _size;
        while(end != npos && end >= pos)
        {
            _str[end + n] = _str[end];
            end--;
        }
        
        for(size_t i = pos; i < n ; i++)
        {
            _str[i] = ch;
        }

        _size += n;
    }
    void insert(size_t pos, const char* str)
    {
        assert(pos <= _size);

        size_t len = strlen(str);
        
        if(_size + len > _capacity)
            reserve((_size + len) * 2);

        size_t end = _size;
        while(end != npos && end >= pos)
        {
            _str[end + len] = _str[end];
            end--;
        }

        for(size_t i = pos; i < len ; i++)
        {
            _str[i] = str[i];
        }

        _size += len;

    }

    void erase(size_t pos, size_t len = npos)
    {
        assert(pos <= _size);

        //pos位置后全删
        if(len == npos || pos + len >= _size)
        {
            _str[pos] = '\0';
            _size = pos;
            _str[_size] = '\0';
        }
        else
        {
            //挪动数据
            size_t end = pos + len;
            while(end <= _size)
            {
                _str[pos++] = _str[end++];
            }
            _size -= len;
        }
    }

    size_t find(const char* str, size_t pos = 0) const
    {
        assert(pos < _size);

        const char* tmp = strstr(_str+pos,str);

        if(str)
            return tmp - _str;

        return npos;
    }

    size_t find(char ch, size_t pos = 0) const
    {
        assert(pos < _size);
        
        for(size_t i = pos; i < _size; i++)
        {
            if(_str[i] == ch)
                return i;
        }

        return npos;

    }
    string substr(size_t pos = 0, size_t len = npos) const 
    {
        assert(pos < _size);

        string tmp;
        size_t n = len;
        //判断长度
        if(len == npos || pos + len > _size)
        {
            n = _size - pos;
        }

        tmp.reserve(n);
        
        //注意边界控制
        for(size_t i = pos; i < n + pos; i++)
        {
            tmp += _str[i];
        }

        return tmp;
    }
    
    void resize(size_t n, char ch = '\0')
    {
        if(n < _size)
        {
            _size = n;
            _str[n] = '\0';
        }
        else
        {
            reserve(n);
            for(size_t i = _size; i < n; i++)
            {
                _str[i] = ch;
            }
            _size = n;
        }


    }

    void clear()
    {
        _str[0] = '\0';
        _size = 0;
    }
    
    bool operator<(const string& s) const
    {
       //先用_str和s._str两个中长度较短的进行比较
        int ret = memcmp(_str, s._str, _size < s._size ? _size : s._size);
        
        //"hello" "hello"    false
        //"hello" "hell"     false
        //"hello" "helloxxx" ture
        return ret == 0 ? _size < s._size : ret < 0;
    }
   
    void swap(string& tmp)
    {
            std::swap(_str,tmp._str);
            std::swap(_size,tmp._size);
            std::swap(_capacity,tmp._capacity);
    }

    string& operator=(const string& s)
    {
        if(*this != s)
        {
            string tmp(s);
            
            swap(tmp);
        }
        return *this;
    }

    bool operator==(const string& s) const
    {
        //长度相等且memcmp返回值为0就相等
        return _size == s._size &&
            memcmp(_str, s._str, _size) == 0;
    }

    bool operator<=(const string& s) const
    {
        return *this < s || *this == s;
    }
    bool operator!=(const string& s) const
    {
        return !(*this == s);
    }
    
    bool operator>(const string& s) const
    {
        return !(*this <= s);
    }
    
    bool operator>=(const string& s) const
    {
        return  !(*this < s);
    }

    private:
        char* _str;
        size_t _capacity;
        size_t _size;
    public:
        const static size_t npos;
    };
    const size_t string::npos = -1;

    ostream& operator<<(ostream& out, const string& s)
    {
        for(auto& e : s)
        {
            out << e;
        }
        return out;
    }

    istream& operator>>(istream& in, string& s)
    {
        //清理string的数据
        s.clear();
        
        char ch = in.get();
        char buff[128] = {'\0'};


        //处理有效字符前的\0和\n
        while(ch == ' ' || ch == '\0')
            ch = in.get();
        
        int i = 0;
        while(ch != ' ' || ch != '\0')
        {
            buff[i++] = ch;
            if(i == 127)
            {
                buff[i] = '\0';
                s += buff;
                i = 0;
            }
            ch = in.get();
        }
        if(i)
        {
            buff[i] = '\0';
            s += buff;
        }
        return in;
    }

}
